我在enable_shared_from_this
阅读Boost.Asio示例时跑了过来,在阅读完文档之后,我仍然因为如何正确使用它而迷失了方向.有人可以给我一个例子和/或说明何时使用这个课程是有道理的.
它可以让你获得一个有效的shared_ptr
实例this
,当你拥有它时this
.没有它,你就没有得到一个的方式shared_ptr
来this
,除非你已经有一个为会员.这个例子来自enable_shared_from_this的boost文档:
class Y: public enable_shared_from_this{ public: shared_ptr f() { return shared_from_this(); } } int main() { shared_ptr p(new Y); shared_ptr q = p->f(); assert(p == q); assert(!(p < q || q < p)); // p and q must share ownership }
方法f()返回一个有效的f()
,即使它没有成员实例.请注意,您不能简单地这样做:
class Y: public enable_shared_from_this{ public: shared_ptr f() { return shared_ptr (this); } }
返回的共享指针将具有与"正确"引用不同的引用计数,并且当删除对象时,其中一个将最终丢失并保持悬空引用.
shared_ptr
已成为C++ 11标准的一部分.你也可以从那里以及从中获得它.
来自Dobbs博士关于弱指针的文章,我认为这个例子更容易理解(来源:http://drdobbs.com/cpp/184402026):
...这样的代码无法正常工作:
int *ip = new int; shared_ptrsp1(ip); shared_ptr sp2(ip);
这两个shared_ptr
对象都不知道另一个,所以两者都会在它们被销毁时尝试释放资源.这通常会导致问题.
类似地,如果一个成员函数需要一个shared_ptr
拥有被调用对象的对象,它就不能只是动态创建一个对象:
struct S { shared_ptrdangerous() { return shared_ptr(this); // don't do this! } }; int main() { shared_ptrsp1(new S); shared_ptrsp2 = sp1->dangerous(); return 0; }
此代码与前面的示例具有相同的问题,但是以更微妙的形式.构造时,shared_pt
r对象sp1
拥有新分配的资源.成员函数S::dangerous
中的代码不知道该shared_ptr
对象,因此shared_ptr
它返回的对象是不同的sp1
.复制新shared_ptr
对象sp2
没有帮助; 当sp2
超出范围时,它将释放资源,当sp1
超出范围时,它将再次释放资源.
避免此问题的方法是使用类模板enable_shared_from_this
.该模板采用一个模板类型参数,该参数是定义受管资源的类的名称.反过来,该类必须从模板中公开派生; 像这样:
struct S : enable_shared_from_this{ shared_ptrnot_dangerous() { return shared_from_this(); } }; int main() { shared_ptrsp1(new S); shared_ptrsp2 = sp1->not_dangerous(); return 0; }
执行此操作时,请记住,您调用的对象shared_from_this
必须由shared_ptr
对象拥有.这不起作用:
int main() { S *p = new S; shared_ptrsp2 = p->not_dangerous(); // don't do this }
这是我的解释,从坚果和螺栓的角度来看(最高的答案并没有'点击'跟我一起).*请注意,这是调查Visual Studio 2012附带的shared_ptr和enable_shared_from_this的源代码的结果.也许其他编译器以不同的方式实现enable_shared_from_this ...*
enable_shared_from_this
添加一个私有weak_ptr
实例,T
其中包含实例的" 一个真实引用计数 " T
.
所以,当你第一次创建一个shared_ptr
新的T*时,那个T*的内部weak_ptr被初始化,其引用数为1.新的shared_ptr
基本上都支持这个weak_ptr
.
T
然后,在其方法中,可以调用shared_from_this
以获取该实例,shared_ptr
该实例返回到相同的内部存储的引用计数.这样,你总是有一个T*
存储ref-count的地方,而不是有多个shared_ptr
彼此不了解的实例,并且每个人认为他们shared_ptr
负责重新计数T
并在他们的引用时删除它-count达到零.